home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / javax / swing / BoxLayout.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  14.5 KB  |  391 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)BoxLayout.java    1.19 98/08/28
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15.  
  16. package javax.swing;
  17.  
  18. import java.awt.*;
  19. import java.io.Serializable;
  20. import java.io.PrintStream;
  21.  
  22. /**
  23.  * A layout manager that allows multiple components to be layed out either
  24.  * vertically or horizontally. The components will not wrap so, for 
  25.  * example, a vertical arrangement of components will stay vertically 
  26.  * arranged when the frame is resized. 
  27.  * <TABLE ALIGN="RIGHT" BORDER="0">
  28.  *    <TR>
  29.  *      <TD ALIGN="CENTER">
  30.  *         <P ALIGN="CENTER"><IMG SRC="doc-files/BoxLayout-1.gif" WIDTH="191" HEIGHT="201" ALIGN="BOTTOM" BORDER="0">
  31.  *      </TD>
  32.  *    </TR>
  33.  * </TABLE>
  34.  * <p>
  35.  * Nesting multiple panels with different combinations of horizontal and 
  36.  * vertical gives an effect similar to GridBagLayout, without the 
  37.  * complexity. The diagram shows two panels arranged horizontally, each 
  38.  * of which contains 3 components arranged vertically.
  39.  * <p>
  40.  * The Box container uses BoxLayout (unlike JPanel, which defaults to flow
  41.  * layout). You can nest multiple boxes and add components to them to get
  42.  * the arrangement you want.
  43.  * <p>
  44.  * The BoxLayout manager that places each of its managed components
  45.  * from left to right or from top to bottom.
  46.  * When you create a BoxLayout, you specify whether its major axis is 
  47.  * the X axis (which means left to right placement) or Y axis (top to 
  48.  * bottom placement). Components are arranged from left to right (or 
  49.  * top to bottom), in the same order as they were added to the container.
  50.  * <p>
  51.  * Instead of using BoxLayout directly, many programs use the Box class.
  52.  * The Box class provides a lightweight container that uses a BoxLayout.
  53.  * Box also provides handy methods to help you use BoxLayout well.
  54.  * <p>
  55.  * BoxLayout attempts to arrange components
  56.  * at their preferred widths (for left to right layout)
  57.  * or heights (for top to bottom layout).
  58.  * For a left to right layout,
  59.  * if not all the components are the same height,
  60.  * BoxLayout attempts to make all the components 
  61.  * as high as the highest component.
  62.  * If that's not possible for a particular component, 
  63.  * then BoxLayout aligns that component vertically,
  64.  * according to the component's Y alignment.
  65.  * By default, a component has an Y alignment of 0.5,
  66.  * which means that the vertical center of the component
  67.  * should have the same Y coordinate as 
  68.  * the vertical centers of other components with 0.5 Y alignment.
  69.  * <p>
  70.  * Similarly, for a vertical layout,
  71.  * BoxLayout attempts to make all components in the column
  72.  * as wide as the widest component;
  73.  * if that fails, it aligns them horizontally
  74.  * according to their X alignments.
  75.  * <p>
  76.  * <strong>Warning:</strong>
  77.  * Serialized objects of this class will not be compatible with
  78.  * future Swing releases.  The current serialization support is appropriate
  79.  * for short term storage or RMI between applications running the same
  80.  * version of Swing.  A future release of Swing will provide support for
  81.  * long term persistence.
  82.  *
  83.  * @see Box
  84.  * @see Component#getAlignmentX
  85.  * @see Component#getAlignmentY
  86.  *
  87.  * @author   Timothy Prinzing
  88.  * @version  1.19 08/28/98
  89.  */
  90. public class BoxLayout implements LayoutManager2, Serializable {
  91.  
  92.     /**
  93.      * Specifies that components should be laid out left to right.
  94.      */
  95.     public static final int X_AXIS = 0;
  96.     
  97.     /**
  98.      * Specifies that components should be laid out top to buttom.
  99.      */
  100.     public static final int Y_AXIS = 1;
  101.  
  102.     /**
  103.      * Creates a layout manager that will lay out components either 
  104.      * left to right or
  105.      * top to bottom,
  106.      * as specified in the <code>axis</code> parameter.  
  107.      *
  108.      * @param target  the container that needs to be laid out
  109.      * @param axis  the axis to lay out components along.
  110.      *              For left-to-right layout, 
  111.      *              specify <code>BoxLayout.X_AXIS</code>;
  112.      *              for top-to-bottom layout, 
  113.      *              specify <code>BoxLayout.Y_AXIS</code>
  114.      *
  115.      * @exception AWTError  if the value of <code>axis</code> is invalid 
  116.      */
  117.     public BoxLayout(Container target, int axis) {
  118.         if (axis != X_AXIS && axis != Y_AXIS) {
  119.             throw new AWTError("Invalid axis");
  120.         }
  121.         this.axis = axis;
  122.         this.target = target;
  123.     }
  124.  
  125.     /**
  126.      * Constructs a BoxLayout that 
  127.      * produces debugging messages.
  128.      *
  129.      * @param target  the container that needs to be laid out
  130.      * @param axis  the axis to lay out components along; can be either
  131.      *              <code>BoxLayout.X_AXIS</code>
  132.      *              or <code>BoxLayout.Y_AXIS</code>
  133.      * @param dbg  the stream to which debugging messages should be sent,
  134.      *   null if none
  135.      */
  136.     BoxLayout(Container target, int axis, PrintStream dbg) {
  137.         this(target, axis);
  138.         this.dbg = dbg;
  139.     }
  140.  
  141.     /**
  142.      * Indicates that a child has changed its layout related information,
  143.      * and thus any cached calculations should be flushed.
  144.      *
  145.      * @param target  the affected container
  146.      *
  147.      * @exception AWTError  if the target isn't the container specified to the
  148.      *                      BoxLayout constructor
  149.      */
  150.     public void invalidateLayout(Container target) {
  151.         checkContainer(target);
  152.         xChildren = null;
  153.         yChildren = null;
  154.         xTotal = null;
  155.         yTotal = null;
  156.     }
  157.  
  158.     /**
  159.      * Not used by this class.
  160.      *
  161.      * @param name the name of the component
  162.      * @param comp the component
  163.      */
  164.     public void addLayoutComponent(String name, Component comp) {
  165.     }
  166.  
  167.     /**
  168.      * Not used by this class.
  169.      *
  170.      * @param comp the component
  171.      */
  172.     public void removeLayoutComponent(Component comp) {
  173.     }
  174.  
  175.     /**
  176.      * Not used by this class.
  177.      *
  178.      * @param comp the component
  179.      * @param constraints constraints
  180.      */
  181.     public void addLayoutComponent(Component comp, Object constraints) {
  182.     }
  183.  
  184.     /**
  185.      * Returns the preferred dimensions for this layout, given the components
  186.      * in the specified target container.
  187.      *
  188.      * @param target  the container that needs to be laid out
  189.      * @return the dimensions >= 0 && <= Integer.MAX_VALUE
  190.      * @exception AWTError  if the target isn't the container specified to the
  191.      *                      BoxLayout constructor
  192.      * @see Container
  193.      * @see #minimumLayoutSize
  194.      * @see #maximumLayoutSize
  195.      */
  196.     public Dimension preferredLayoutSize(Container target) {
  197.         checkContainer(target);
  198.         checkRequests();
  199.  
  200.         Dimension size = new Dimension(xTotal.preferred, yTotal.preferred);
  201.         Insets insets = target.getInsets();
  202.         size.width = (int) Math.min((long) size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE);
  203.         size.height = (int) Math.min((long) size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE);
  204.         return size;
  205.     }
  206.  
  207.     /**
  208.      * Returns the minimum dimensions needed to lay out the components
  209.      * contained in the specified target container.
  210.      *
  211.      * @param target  the container that needs to be laid out 
  212.      * @return the dimensions >= 0 && <= Integer.MAX_VALUE
  213.      * @exception AWTError  if the target isn't the container specified to the
  214.      *                      BoxLayout constructor
  215.      * @see #preferredLayoutSize
  216.      * @see #maximumLayoutSize
  217.      */
  218.     public Dimension minimumLayoutSize(Container target) {
  219.         checkContainer(target);
  220.         checkRequests();
  221.  
  222.         Dimension size = new Dimension(xTotal.minimum, yTotal.minimum);
  223.         Insets insets = target.getInsets();
  224.         size.width = (int) Math.min((long) + size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE);
  225.         size.height = (int) Math.min((long) + size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE);
  226.         return size;
  227.     }
  228.  
  229.     /**
  230.      * Returns the maximum dimensions the target container can use
  231.      * to lay out the components it contains.
  232.      *
  233.      * @param target  the container that needs to be laid out 
  234.      * @return the dimenions >= 0 && <= Integer.MAX_VALUE
  235.      * @exception AWTError  if the target isn't the container specified to the
  236.      *                      BoxLayout constructor
  237.      * @see #preferredLayoutSize
  238.      * @see #minimumLayoutSize
  239.      */
  240.     public Dimension maximumLayoutSize(Container target) {
  241.         checkContainer(target);
  242.         checkRequests();
  243.  
  244.         Dimension size = new Dimension(xTotal.maximum, yTotal.maximum);
  245.         Insets insets = target.getInsets();
  246.         size.width = (int) Math.min((long) size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE);
  247.         size.height = (int) Math.min((long) size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE);
  248.         return size;
  249.     }
  250.  
  251.     /**
  252.      * Returns the alignment along the X axis for the container.
  253.      * If the box is horizontal, the default
  254.      * alignment will be returned. Otherwise, the alignment needed
  255.      * to place the children along the X axis will be returned.
  256.      *
  257.      * @param target  the container
  258.      * @return the alignment >= 0.0f && <= 1.0f
  259.      * @exception AWTError  if the target isn't the container specified to the
  260.      *                      BoxLayout constructor
  261.      */
  262.     public float getLayoutAlignmentX(Container target) {
  263.         checkContainer(target);
  264.         checkRequests();
  265.         return xTotal.alignment;
  266.     }
  267.  
  268.     /**
  269.      * Returns the alignment along the Y axis for the container.
  270.      * If the box is vertical, the default
  271.      * alignment will be returned. Otherwise, the alignment needed
  272.      * to place the children along the Y axis will be returned.
  273.      *
  274.      * @param target  the container
  275.      * @return the alignment >= 0.0f && <= 1.0f
  276.      * @exception AWTError  if the target isn't the container specified to the
  277.      *                      BoxLayout constructor
  278.      */
  279.     public float getLayoutAlignmentY(Container target) {
  280.         checkContainer(target);
  281.         checkRequests();
  282.         return yTotal.alignment;
  283.     }
  284.  
  285.     /**
  286.      * Called by the AWT <!-- XXX CHECK! --> when the specified container
  287.      * needs to be laid out.
  288.      *
  289.      * @param target  the container to lay out
  290.      *
  291.      * @exception AWTError  if the target isn't the container specified to the
  292.      *                      BoxLayout constructor
  293.      */
  294.     public void layoutContainer(Container target) {
  295.         checkContainer(target);
  296.         checkRequests();
  297.         
  298.         int nChildren = target.getComponentCount();
  299.         int[] xOffsets = new int[nChildren];
  300.         int[] xSpans = new int[nChildren];
  301.         int[] yOffsets = new int[nChildren];
  302.         int[] ySpans = new int[nChildren];
  303.  
  304.         // determine the child placements
  305.         Dimension alloc = target.getSize();
  306.         Insets in = target.getInsets();
  307.         alloc.width -= in.left + in.right;
  308.         alloc.height -= in.top + in.bottom;
  309.         if (axis == X_AXIS) {
  310.             SizeRequirements.calculateTiledPositions(alloc.width, xTotal,
  311.                                                      xChildren, xOffsets,
  312.                                                      xSpans);
  313.             SizeRequirements.calculateAlignedPositions(alloc.height, yTotal,
  314.                                                        yChildren, yOffsets,
  315.                                                        ySpans);
  316.         } else {
  317.             SizeRequirements.calculateAlignedPositions(alloc.width, xTotal,
  318.                                                        xChildren, xOffsets,
  319.                                                        xSpans);
  320.             SizeRequirements.calculateTiledPositions(alloc.height, yTotal,
  321.                                                      yChildren, yOffsets,
  322.                                                      ySpans);
  323.         }
  324.  
  325.         // flush changes to the container
  326.         for (int i = 0; i < nChildren; i++) {
  327.             Component c = target.getComponent(i);
  328.             c.setBounds((int) Math.min((long) in.left + (long) xOffsets[i], Integer.MAX_VALUE),
  329.                         (int) Math.min((long) in.top + (long) yOffsets[i], Integer.MAX_VALUE),
  330.                         xSpans[i], ySpans[i]);
  331.  
  332.         }
  333.         if (dbg != null) {
  334.             for (int i = 0; i < nChildren; i++) {
  335.                 Component c = target.getComponent(i);
  336.                 dbg.println(c.toString());
  337.                 dbg.println("X: " + xChildren[i]);
  338.                 dbg.println("Y: " + yChildren[i]);
  339.             }
  340.         }
  341.             
  342.     }
  343.  
  344.     void checkContainer(Container target) {
  345.         if (this.target != target) {
  346.             throw new AWTError("BoxLayout can't be shared");
  347.         }
  348.     }
  349.     
  350.     void checkRequests() {
  351.         if (xChildren == null || yChildren == null) {
  352.             // The requests have been invalidated... recalculate
  353.             // the request information.
  354.             int n = target.getComponentCount();
  355.             xChildren = new SizeRequirements[n];
  356.             yChildren = new SizeRequirements[n];
  357.             for (int i = 0; i < n; i++) {
  358.                 Component c = target.getComponent(i);
  359.                 Dimension min = c.getMinimumSize();
  360.                 Dimension typ = c.getPreferredSize();
  361.                 Dimension max = c.getMaximumSize();
  362.                 xChildren[i] = new SizeRequirements(min.width, typ.width, 
  363.                                                     max.width, 
  364.                                                     c.getAlignmentX());
  365.                 yChildren[i] = new SizeRequirements(min.height, typ.height, 
  366.                                                     max.height, 
  367.                                                     c.getAlignmentY());
  368.             }
  369.             
  370.             if (axis == X_AXIS) {
  371.                 xTotal = SizeRequirements.getTiledSizeRequirements(xChildren);
  372.                 yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren);
  373.             } else {
  374.                 xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren);
  375.                 yTotal = SizeRequirements.getTiledSizeRequirements(yChildren);
  376.             }
  377.         }
  378.     }
  379.             
  380.     private int axis;
  381.     private Container target;
  382.  
  383.     private transient SizeRequirements[] xChildren;
  384.     private transient SizeRequirements[] yChildren;
  385.     private transient SizeRequirements xTotal;
  386.     private transient SizeRequirements yTotal;
  387.     
  388.     private transient PrintStream dbg;
  389. }
  390.  
  391.